package com.liaoyifan.core.config;

import com.liaoyifan.core.constant.Constants;
import com.liaoyifan.core.constant.Properties;
import com.liaoyifan.core.converter.RedisConverter;
import com.liaoyifan.core.properties.RedisProperties;
import com.liaoyifan.core.util.Json;
import com.liaoyifan.core.util.Redis;
import com.liaoyifan.core.valid.Assert;
import com.liaoyifan.core.valid.Lang;
import java.util.Arrays;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.redisson.connection.balancer.RoundRobinLoadBalancer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;

@SuppressWarnings("unused")
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
@Import(Redis.class)
@ConditionalOnProperty(name = Properties.REDIS_ENABLE, havingValue = Constants.TRUE)
public class RedisConfiguration {

    @Autowired private RedisProperties properties;

    @Bean(destroyMethod = "shutdown", name = "redisson")
    @Primary
    public RedissonClient redisson() {
        Config config = new Config();
        Assert.notBlank(properties.getAddress(), "Redis address cannot be null");
        // 设置线程池大小
        config.setThreads(Constants.CPU_COUNT * 2);
        config.setNettyThreads(Constants.CPU_COUNT * 2);
        String[] address = Lang.split(properties.getAddress(), ",");
        if (address.length > Constants.ONE) {
            // 集群模式配置
            ClusterServersConfig server = config.useClusterServers();
            RedisConverter.INSTANCE.toClusterConfig(properties, server);
            server.addNodeAddress(
                    Arrays.stream(address).map(i -> "redis://" + i).toArray(String[]::new));
            server.setLoadBalancer(new RoundRobinLoadBalancer());
        } else {
            // 单机模式配置
            SingleServerConfig server = config.useSingleServer();
            RedisConverter.INSTANCE.toSingleServerConfig(properties, server);
            server.setAddress("redis://" + address[0]);
        }
        // 配置序列化器
        config.setCodec(new JsonJacksonCodec(Json.OBJECT_MAPPER));
        return Redisson.create(config);
    }
}
